package cn.gxufe.reliable.message.admin.schedule.consumer;

import cn.gxufe.reliable.message.admin.domain.RMessage;
import cn.gxufe.reliable.message.admin.mapper.MessageMapper;
import cn.gxufe.reliable.message.admin.schedule.AbstractSchedule;
import cn.gxufe.reliable.message.admin.utils.PublishUtils;
import cn.gxufe.reliable.message.common.Message;
import cn.gxufe.reliable.message.common.ResultVo;
import com.netflix.hystrix.HystrixCommand;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.ResponseEntity;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Service;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;

import java.util.Date;
import java.util.List;

/**
 * @author yingjie.rong
 **/
@Service
public class TryFinishOrCancelService extends AbstractSchedule {

    private static final Logger logger = LoggerFactory.getLogger(TryFinishOrCancelService.class);


    @Autowired
    private MessageMapper messageMapper;
    @Scheduled(fixedDelay = 1000)
    public void exec(){
        List<RMessage> messages = messageMapper.selectTryFinishOrCancel(new Date(System.currentTimeMillis() - (3 * 1000)));
        for (RMessage message: messages ) {
            tryFinishOrCancel(message);
        }
    }


    public void tryFinishOrCancel(RMessage message){
        MultiValueMap<String, Object> requestEntity = new LinkedMultiValueMap<>();
        requestEntity.add("messageId", message.getId());
        requestEntity.add("key", message.getKey());
        requestEntity.add("header", message.getHeader());
        HystrixCommand<ResultVo> hystrixCommand =  this.getHystrixCommand(message.getTargetService(),(t) -> {
            String url = "http://" + message.getTargetService() + TRY_FINISH_CANCEL;
            ResponseEntity<ResultVo> responseEntity = restTemplate.postForEntity(url, requestEntity, ResultVo.class);
            return responseEntity.getBody();
        }, ResultVo.error(-1,"fallback"));

        ResultVo resultVo = hystrixCommand.execute();
        if(hystrixCommand.isSuccessfulExecution()){
            if( resultVo.get( ResultVo.CODE ).equals( Message.RESPONSE_CODE_OK )){
                Integer newStatus = Integer.valueOf(resultVo.get(ResultVo.MSG).toString());
                logger.info("id = {}, key ={} ,new status = {} call finishOrCancel successful !",message.getId(), message.getKey(),newStatus);
                messageMapper.updateFinishOrCancel(newStatus,RMessage.STATUS_TRY_FINISH ,message.getFinishData(),message.getTargetService(),message.getId());
                message.setStatus(newStatus);
                PublishUtils.publish( message );
            }else if( resultVo.get( ResultVo.CODE ).equals( Message.RESPONSE_CODE_NOT_FOUNT )){
                logger.info("id = {}, key ={}  call finishOrCancel successful  but not found , will  resend to mq ",message.getId(), message.getKey());
                messageMapper.updateFinishOrCancel(Message.STATUS_CONFIRM,RMessage.STATUS_TRY_FINISH ,message.getFinishData(),message.getTargetService(),message.getId());
            } else {
                logger.warn( message.toString()+"\tcode = " +  resultVo.get( ResultVo.CODE ) +"\tstatus = " +  resultVo.get( ResultVo.MSG ));
            }
        } else {
            hystrixCommand.getExecutionException().printStackTrace();
            logger.warn("id = {}, key ={} call finish error !",message.getId(), message.getKey());
            messageMapper.updateFinish(RMessage.STATUS_TRY_FINISH, message.getId(),0,0);
        }
    }
}
